package scf.demo.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.module.blackbird.BlackbirdModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Map;
import java.util.TreeMap;

import static cn.hutool.core.date.DatePattern.*;

/**
 * @author Harry Lee
 * @since 2024/9/14 14:59
 */
@Configuration
public class JacksonConfig {

    /**
     * 注册黑鸟模块，优化jackson性能
     *
     * @param mapper ObjectMapper
     */
    @Autowired
    public void config(ObjectMapper mapper) {
        mapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
        mapper.disable(SerializationFeature.INDENT_OUTPUT);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setDateFormat(new SimpleDateFormat(NORM_DATETIME_PATTERN));
        var blackbirdModule = new BlackbirdModule();
        mapper.registerModule(blackbirdModule);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(NORM_DATETIME_FORMATTER));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(NORM_DATE_FORMATTER));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(NORM_TIME_FORMATTER));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(NORM_DATETIME_FORMATTER));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(NORM_DATE_FORMATTER));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(NORM_TIME_FORMATTER));
        mapper.registerModule(javaTimeModule);
        // TreeMap 默认按key排序（ASCII）
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Map.class, new JsonDeserializer<>() {
            @Override
            public Map deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                // 检查当前token是否为开始对象
                if (p.getCurrentToken() == JsonToken.START_OBJECT) {
                    Map<String, Object> sortedMap = new TreeMap<>();
                    p.nextToken();
                    while (p.getCurrentToken() != JsonToken.END_OBJECT) {
                        String fieldName = p.currentName();
                        p.nextToken();
                        Object value = p.readValueAs(Object.class);
                        sortedMap.put(fieldName, value);
                        p.nextToken();
                    }
                    return sortedMap;
                }
                return ctxt.readValue(p, Map.class);
            }
        });
        mapper.registerModule(module);
    }

}
